/// <reference path="../../../inig.d.ts" />

import localforage from 'localforage'
import { GlobalData } from '../global'

export const userStore = localforage.createInstance({
  name: 'inig',
  storeName: 'user',
})

type LocalForageParams = {
  /**
   * localforage前置key
   * @type string
   */
  key: string

  /**
   * localforage失效时间，单位毫秒，不传expiredAt或(expiredAt为0)时，不失效
   * @type number
   */
  expiredAt?: number

  /**
   * 存储库
   * @type LocalForage
   */
  store?: LocalForage

  /**
   * 待存储的数据
   * @type any
   */
  data?: any
}

function getLocalforageKey(params: LocalForageParams): string {
  if (params.expiredAt) {
    return params.key + '-' + new Date().getTime() + ':' + params.expiredAt
  } else {
    return params.key
  }
}

export function isExpired(params: LocalForageParams): boolean {
  let key = params.key
  let matched = key.match(/\d{13}:\d{1,}$/)
  if (!matched) {
    // 无过期时间，永不失效
    return false
  } else {
    let startTs = matched[0].split(':')[0]
    let expiredAt = matched[0].split(':')[1]
    if (Number(startTs) + Number(expiredAt) <= new Date().getTime()) {
      // 缓存过期，删除缓存
      if (params.store) {
        params.store.removeItem(key)
      }
      return true
    } else {
      return false
    }
  }
}

function findRealKey(params: LocalForageParams): Promise<Array<any>> {
  return new Promise(async (resolve) => {
    if (!params.store) {
      resolve([])
    } else if (!params.key) {
      resolve([])
    } else {
      await params.store
        .keys()
        .then((keys: any[]) => {
          resolve(keys.filter((item) => item.indexOf(params.key) === 0))
        })
        .catch(() => {
          resolve([])
        })
    }
  })
}

export function getItem(params: LocalForageParams): Promise<any> {
  return new Promise(async (resolve, reject) => {
    if (GlobalData.isServer || GlobalData.isTest) {
      resolve(null)
    } else if (!params.store) {
      // reject(new Error('数据仓库 [store] 不能为空 '))
      resolve(null)
    } else if (!params.key) {
      // reject(new Error('缓存名称 [key] 不能为空'))
      resolve(null)
    } else {
      let _localedKey = await findRealKey(params)
      if (_localedKey && _localedKey[0]) {
        let _isExpired = isExpired({
          key: _localedKey[0],
          store: params.store,
        })
        if (_isExpired) {
          resolve(null)
        } else {
          let d = await params.store.getItem(_localedKey[0])
          resolve(d)
        }
      } else {
        resolve(null)
      }
    }
  })
}

export function setItem(params: LocalForageParams): Promise<Boolean> {
  return new Promise(async (resolve, reject) => {
    if (GlobalData.isServer || GlobalData.isTest) {
      resolve(true)
    } else if (!params.store) {
      reject(new Error('数据仓库 [store] 不能为空'))
    } else if (!params.key) {
      reject(new Error('缓存名称 [key] 不能为空'))
    } else {
      await removeItem(params)
      let _realKey = getLocalforageKey({
        key: params.key,
        expiredAt: params.expiredAt,
      })
      await params.store.setItem(_realKey, params.data)
      resolve(true)
    }
  })
}

export function removeItem(params: LocalForageParams): Promise<Boolean> {
  return new Promise(async (resolve, reject) => {
    if (GlobalData.isServer || GlobalData.isTest) {
      resolve(true)
    } else if (!params.store) {
      reject(new Error('数据仓库 [store] 不能为空'))
    } else if (!params.key) {
      reject(new Error('缓存名称 [key] 不能为空'))
    } else {
      let _localedKey = await findRealKey(params)
      if (_localedKey) {
        _localedKey.forEach((item) => {
          params.store?.removeItem(item)
        })
      }
      resolve(true)
    }
  })
}
